package com.ruoyi.system.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.config.GeoProperties;
import com.ruoyi.system.service.IGeoLocationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 地理位置服务实现
 * 
 * @author ruoyi
 */
@Service
public class GeoLocationServiceImpl implements IGeoLocationService 
{
    private static final Logger log = LoggerFactory.getLogger(GeoLocationServiceImpl.class);
    
    @Autowired
    private RedisService redisService;
    
    @Autowired
    private GeoProperties geoProperties;
    
    private final WebClient webClient;
    private final ObjectMapper objectMapper;
    
    public GeoLocationServiceImpl() {
        this.webClient = WebClient.builder()
                .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024 * 1024))
                .build();
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public AjaxResult getLocationByAddress(String address) 
    {
        if (address == null || address.trim().isEmpty()) {
            return AjaxResult.error("地址不能为空");
        }
        
        // 检查缓存
        String cacheKey = "geo:address:" + address.hashCode();
        GeoLocationResult cached = redisService.getCacheObject(cacheKey);
        if (cached != null) {
            return AjaxResult.success(cached);
        }
        
        try {
            String url;
            if ("tencent".equals(geoProperties.getProvider())) {
                // 腾讯地图地理编码 - 使用address参数
                url = geoProperties.getTencent().getUrl() + "?key=" + geoProperties.getTencent().getKey() + 
                      "&address=" + java.net.URLEncoder.encode(address, "UTF-8");
                log.info("腾讯地图地理编码请求URL: {}", url);
            } else {
                // 高德地图地理编码
                url = geoProperties.getAmap().getUrl() + "?key=" + geoProperties.getAmap().getKey() + 
                      "&address=" + java.net.URLEncoder.encode(address, "UTF-8");
            }
            
            String response = webClient.get()
                    .uri(url)
                    .retrieve()
                    .bodyToMono(String.class)
                    .timeout(Duration.ofSeconds(10))
                    .block();
            
            JsonNode root = objectMapper.readTree(response);
            GeoLocationResult result;
            
            if ("tencent".equals(geoProperties.getProvider())) {
                // 腾讯地图响应处理
                log.info("腾讯地图API响应: {}", response);
                
                JsonNode statusNode = root.get("status");
                if (statusNode == null) {
                    log.error("腾讯地图API响应缺少status字段: {}", response);
                    return AjaxResult.error("腾讯地图API响应格式错误");
                }
                
                int status = statusNode.asInt();
                if (status != 0) {
                    String message = root.has("message") ? root.get("message").asText() : "未知错误";
                    log.error("腾讯地图地理编码API调用失败: status={}, message={}", status, message);
                    return AjaxResult.error("地址解析失败: " + message);
                }
                
                JsonNode resultNode = root.get("result");
                if (resultNode == null) {
                    log.error("腾讯地图API响应缺少result字段: {}", response);
                    return AjaxResult.error("未找到该地址的坐标信息");
                }
                
                JsonNode location = resultNode.get("location");
                if (location == null) {
                    log.error("腾讯地图API响应缺少location字段: {}", response);
                    return AjaxResult.error("未找到该地址的坐标信息");
                }
                
                result = new GeoLocationResult();
                result.setLongitude(location.has("lng") ? location.get("lng").asText() : "");
                result.setLatitude(location.has("lat") ? location.get("lat").asText() : "");

                // 兼容多种字段作为格式化地址：title > address > 输入地址
                String formattedAddress = address;
                if (resultNode.hasNonNull("title")) {
                    formattedAddress = resultNode.get("title").asText();
                } else if (resultNode.hasNonNull("address")) {
                    formattedAddress = resultNode.get("address").asText();
                }
                result.setFormattedAddress(formattedAddress);

                // 兼容 address_components / address_component / ad_info 三种结构
                String province = "";
                String city = "";
                String district = "";

                JsonNode addressComponents = null;
                if (resultNode.has("address_components")) {
                    addressComponents = resultNode.get("address_components");
                } else if (resultNode.has("address_component")) {
                    addressComponents = resultNode.get("address_component");
                }
                if (addressComponents != null) {
                    province = addressComponents.has("province") ? addressComponents.get("province").asText("") : province;
                    city = addressComponents.has("city") ? addressComponents.get("city").asText("") : city;
                    district = addressComponents.has("district") ? addressComponents.get("district").asText("") : district;
                }
                // 兜底从 ad_info 读取
                JsonNode adInfo = resultNode.get("ad_info");
                if (adInfo != null) {
                    if (province.isEmpty() && adInfo.has("province")) province = adInfo.get("province").asText("");
                    if (city.isEmpty() && adInfo.has("city")) city = adInfo.get("city").asText("");
                    if (district.isEmpty() && adInfo.has("district")) district = adInfo.get("district").asText("");
                }

                result.setProvince(province);
                result.setCity(city);
                result.setDistrict(district);

                result.setAddress(address);
            } else {
                // 高德地图响应处理
                String status = root.get("status").asText();
                if (!"1".equals(status)) {
                    String info = root.get("info").asText();
                    log.error("高德地理编码API调用失败: {}", info);
                    return AjaxResult.error("地址解析失败: " + info);
                }
                
                JsonNode geocodes = root.get("geocodes");
                if (geocodes == null || geocodes.size() == 0) {
                    return AjaxResult.error("未找到该地址的坐标信息");
                }
                
                JsonNode firstResult = geocodes.get(0);
                String location = firstResult.get("location").asText();
                String[] coords = location.split(",");
                
                result = new GeoLocationResult();
                result.setLongitude(coords[0]);
                result.setLatitude(coords[1]);
                result.setFormattedAddress(firstResult.get("formatted_address").asText());
                result.setProvince(firstResult.get("province").asText());
                result.setCity(firstResult.get("city").asText());
                result.setDistrict(firstResult.get("district").asText());
                result.setAddress(address);
            }
            
            // 缓存结果，有效期1小时
            redisService.setCacheObject(cacheKey, result, 3600L, TimeUnit.SECONDS);
            
            return AjaxResult.success(result);
            
        } catch (Exception e) {
            log.error("获取地址坐标失败", e);
            return AjaxResult.error("获取地址坐标失败: " + e.getMessage());
        }
    }

    
}
